using System.Net.Sockets;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace WpfApp_ChenxiConsole.TCP
{
    /// <summary>
    /// TcpConsoleControl.xaml 的交互逻辑
    /// </summary>
    public partial class TcpConsoleControl : UserControl
    {
        // 使用TcpClientManager处理TCP通信
        private TcpClientManager? tcpClientManager;
        
        /// <summary>
        /// 获取TCP客户端管理器实例（用于调试）
        /// </summary>
        public TcpClientManager? TcpClientManager
        {
            get { return tcpClientManager; }
        }
        
        /// <summary>
        /// 获取TCP客户端是否已连接
        /// </summary>
        public bool IsConnected
        {
            get 
            {
                // 确保tcpClientManager不为空且已连接
                return tcpClientManager != null && tcpClientManager.IsConnected();
            }
        }

        // 跟踪是否显示时间戳
        private bool showTimestamp = false;
        
        // 当前段落，用于合并无时间戳的消息
        private Paragraph? currentParagraph = null;

        public TcpConsoleControl()
        {
            InitializeComponent();
            // 注册编码提供程序以支持GB2312等编码
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        }

        private async void ConnectButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // 获取用户输入的IP地址和端口号
                string ipAddress = IpAddressTextBox.Text;
                int port = int.Parse(PortTextBox.Text);

                // 创建TcpClientManager实例
                tcpClientManager = new TcpClientManager(
                    Dispatcher,
                    AppendTextToRecvTextBox,
                    OnConnectionClosed,
                    // 添加更新连接状态指示器颜色的回调函数
                    (brush) => { TCPLinkPointer.Fill = brush; }
                );

                // 尝试连接
                bool isConnected = await tcpClientManager.ConnectAsync(ipAddress, port);

                if (isConnected)
                {
                    // 连接成功
                    AppendTextToRecvTextBox($"成功连接到 {ipAddress}:{port}", "连接");
                    ConnectButton.IsEnabled = false;
                }
                else
                {
                    AppendTextToRecvTextBox($"连接失败", "错误");
                }
            }
            catch (Exception ex)
            {
                // 显示错误信息
                AppendTextToRecvTextBox($"连接失败：{ex.Message}", "错误");
                MessageBox.Show($"连接失败：{ex.Message}");
            }
        }

        // 在UI线程上更新RichTextBox - 支持添加时间戳和消息类型，以及根据消息类型设置不同颜色
        private void AppendTextToRecvTextBox(string text, string messageType = "")
        {
            if (Dispatcher.CheckAccess())
            {
                // 为不同类型的消息设置不同的颜色
                SolidColorBrush textBrush = Brushes.Black; // 默认黑色
                if (messageType == "发>> ")
                {
                    textBrush = new SolidColorBrush(Color.FromRgb(0, 120, 215)); // 好看的蓝色
                }
                else if (messageType == "错误")
                {
                    textBrush = Brushes.Red; // 错误消息为红色
                }
                else if (messageType == "连接" || messageType == "断开")
                {
                    textBrush = Brushes.Green; // 连接相关消息为绿色
                }

                if (showTimestamp)
                {
                    // 选中时间戳模式：为每条消息创建新段落，自动换行
                    Paragraph paragraph = new() { LineHeight = 1.05 };
                    paragraph.LineHeight = 1.05; // 设置更紧凑的行高
                    RecvTextBox.Document.Blocks.Add(paragraph);

                    // 添加时间戳和消息类型（灰色）
                    if (!string.IsNullOrEmpty(messageType))
                    {
                        string timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
                        Run timestampRun = new($"[{timestamp}]{messageType}")
                        {
                            Foreground = Brushes.Gray
                        };
                        paragraph.Inlines.Add(timestampRun);
                    }

                    // 添加消息内容并设置颜色
                    Run contentRun = new(text)
                    {
                        Foreground = textBrush
                    };
                    paragraph.Inlines.Add(contentRun);
                }
                else
                {
                    // 未选中时间戳模式：合并到当前段落，不自动换行
                    if (currentParagraph == null)
                    {
                        currentParagraph = new Paragraph() { LineHeight = 1.05 };
                        RecvTextBox.Document.Blocks.Add(currentParagraph);
                    }

                    // 添加消息内容并设置颜色，不添加时间戳
                    Run contentRun = new(text)
                    {
                        Foreground = textBrush
                    };
                    currentParagraph.Inlines.Add(contentRun);
                }

                // 滚动到底部
                RecvTextBox.ScrollToEnd();
            }
            else
            {
                // 通过Dispatcher在UI线程上执行
                Dispatcher.Invoke(() => AppendTextToRecvTextBox(text, messageType));
            }
        }

        private void DisconnectButton_Click(object sender, RoutedEventArgs e)
        {
            // 使用TcpClientManager断开连接
            if (tcpClientManager != null && tcpClientManager.IsConnected())
            {
                try
                {
                    tcpClientManager.Disconnect();
                    AppendTextToRecvTextBox("已断开连接", "断开");
                }
                catch (Exception ex)
                {
                    AppendTextToRecvTextBox($"断开连接错误：{ex.Message}", "错误");
                }
            }
        }

        /// <summary>
        /// 当连接关闭时调用的回调函数
        /// </summary>
        private void OnConnectionClosed()
        {
            // 重新启用连接按钮
            ConnectButton.IsEnabled = true;
        }

        private void TimestampCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            showTimestamp = true;
            // 切换到显示时间戳模式时，创建一个新段落
            currentParagraph = null;
        }

        private void TimestampCheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            showTimestamp = false;
            // 切换到不显示时间戳模式时，确保有一个当前段落用于合并消息
            if (RecvTextBox.Document.Blocks.Count == 0 || currentParagraph == null)
            {
                currentParagraph = new Paragraph() { LineHeight = 1.05 };
                RecvTextBox.Document.Blocks.Add(currentParagraph);
            }
        }

        private void ClearSendButton_Click(object sender, RoutedEventArgs e)
        {
            // 清空发送文本框
            SendTextBox.Document.Blocks.Clear();
        }

        private async void SendButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // 检查TCP连接是否已建立
                if (tcpClientManager != null && tcpClientManager.IsConnected())
                {
                    // 获取发送文本框中的内容
                string message = new TextRange(SendTextBox.Document.ContentStart, SendTextBox.Document.ContentEnd).Text.Trim();

                if (!string.IsNullOrEmpty(message))
                {
                    // 根据自动换行复选框状态处理消息
                    if (AutoNewLineCheckBox.IsChecked == true)
                    {
                        // 如果勾选了自动换行，确保消息末尾有换行符
                        if (!message.EndsWith("\r\n") && !message.EndsWith("\n"))
                        {
                            message += "\r\n";
                        }
                    }
                    else
                    {
                        // 如果未勾选自动换行，移除消息末尾的换行符
                        message = message.TrimEnd('\r', '\n');
                    }

                    // 获取用户选择的编码格式
                    string selectedEncoding = EncodingComboBox.SelectedItem is ComboBoxItem item && item.Content != null
                        ? item.Content.ToString() ?? string.Empty
                        : string.Empty;
                    Encoding encoding = GetEncodingByName(selectedEncoding);

                    // 发送消息，使用选择的编码格式
                    bool isSent = await tcpClientManager.SendMessageAsync(message, encoding);

                        if (isSent)
                        {
                            // 显示发送成功的消息
                            AppendTextToRecvTextBox($"{message}", "发>> ");
                            // 保留发送文本框中的内容，不做清空操作
                        }
                        else
                        {
                            AppendTextToRecvTextBox("发送失败", "错误");
                        }
                    }
                }
                else
                {
                    AppendTextToRecvTextBox("未连接到服务器", "错误");
                }
            }
            catch (Exception ex)
            {
                AppendTextToRecvTextBox($"发送错误：{ex.Message}", "错误");
            }
        }

        /// <summary>
        /// 根据编码名称获取对应的Encoding对象
        /// </summary>
        /// <param name="encodingName">编码名称</param>
        /// <returns>对应的Encoding对象</returns>
        private static Encoding GetEncodingByName(string encodingName)
        {
            return encodingName switch
            {
                "UTF-8" => Encoding.UTF8,
                "ASCII" => Encoding.ASCII,
                "GB2312" =>Encoding.GetEncoding("GB2312"),
                "GBK" => Encoding.GetEncoding("GBK"),
                "Unicode" => Encoding.Unicode,
                _ => Encoding.UTF8, // 默认使用UTF-8
            };
        }
    }
}